﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace C4F.DevKit.Speech.Controls
{
    [ToolboxItem(true), ToolboxBitmap(typeof(SpeechSettings))]
    public partial class SpeechSettings : UserControl
    {
        public delegate void SettingsAppliedEventHandler(object sender, EventArgs e);
        public event SettingsAppliedEventHandler SettingsApplied;

        public delegate void SettingsCanceledEventHandler(object sender, EventArgs e);
        public event SettingsCanceledEventHandler SettingsCanceled;

        #region Constants

        private const string DESIGNER_CATEGORY = "Speech";

        #endregion Constants

        #region Private variables
        
        private int _speechVolume = 0;
        private int _speechRate = 0;
        private SapiManager _sapiManager = null;
        private List<VoiceInfo> _voices;

        #endregion Private variables

        #region Properties

        /// <summary>
        /// The SAPI Manager component
        /// </summary>
        [Browsable(true), Category(DESIGNER_CATEGORY)]
        public SapiManager SapiManager
        {
            get { return _sapiManager; }
            set
            {
                _sapiManager = value;

                if (!this.DesignMode && _sapiManager != null)
                {
                    try
                    {
                        _voices = _sapiManager.Voices;
                        FillInstalledVoicesInComboBox();

                        PopulateProperties();


                    }
                    catch
                    {
                        MessageBox.Show("Unable to find installed voices, Application will use default voice!", "SpeechGUI", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                else if (_sapiManager == null)
                {
                    _voices = null;
                }
            }
        }

        #endregion Properties

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the SpeechSettings control.
        /// </summary>
        public SpeechSettings()
        {
            InitializeComponent();
        }

        #endregion Constructor

        #region Methods

        #region Event Handlers

        private void trackBarVolume_Scroll(object sender, EventArgs e)
        {
            _speechVolume = trackBarVolume.Value;
        }

        private void trackBarRate_Scroll(object sender, EventArgs e)
        {
            _speechRate = trackBarRate.Value;
        }

        private void rdPersonName_CheckedChanged(object sender, EventArgs e)
        {
            if (rdPersonName.Checked == true)
            {
                try
                {
                    FillInstalledVoicesInComboBox();
                    cmbPersons.Enabled = true;
                    cmbGender.Enabled = false;
                    cmbAge.Enabled = false;
                }
                catch
                {
                    MessageBox.Show("Unable to find installed voices, Application will use default voice!", "SpeechGUI", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void rdSelectGender_CheckedChanged(object sender, EventArgs e)
        {
            if (rdSelectGender.Checked == true)
            {
                try
                {
                    FillInstalledVoicesGendersInComboBox();
                    cmbPersons.Enabled = false;
                    cmbGender.Enabled = true;
                    cmbAge.Enabled = true;
                }
                catch
                {
                    MessageBox.Show("Unable to find installed voices, Application will use default voice!", "SpeechGUI", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void cmbGender_SelectedIndexChanged(object sender, EventArgs e)
        {
            FillInstalledVoicesAgeInComboBox();
        }

        private void btnApply_Click(object sender, EventArgs e)
        {
            OnApplySettings();
            OnApplied(new EventArgs());
        }

        #endregion Event Handlers

        #region Private

        private void FillInstalledVoicesGendersInComboBox()
        {
            cmbGender.Items.Clear();
            foreach (VoiceInfo v in _voices)
            {
                if (!CheckIfAlreadyExists(cmbGender.Items, v.Gender.ToString()))
                {
                    cmbGender.Items.Add(v.Gender.ToString());
                }
            }
            if (cmbGender.Items.Count > 0)
            {
                cmbGender.SelectedIndex = 0;
            }
        }

        private void FillInstalledVoicesAgeInComboBox()
        {
            cmbAge.Items.Clear();
            foreach (VoiceInfo v in _voices)
            {
                if (cmbGender.Text == v.Gender.ToString())
                {
                    if (!CheckIfAlreadyExists(cmbAge.Items, v.Age.ToString()))
                    {
                        cmbAge.Items.Add(v.Age.ToString());
                    }
                }
            }

            if (cmbAge.Items.Count > 0)
            {
                cmbAge.SelectedIndex = 0;
            }
        }

        private void FillInstalledVoicesInComboBox()
        {
            cmbPersons.Items.Clear();
            foreach (VoiceInfo v in _voices)
            {
                cmbPersons.Items.Add(v.Name);
            }
            if (cmbPersons.Items.Count > 0)
            {
                cmbPersons.SelectedIndex = 0;
            }
        }

        private void OnApplySettings()
        {
            this.SapiManager.VoiceRate = _speechRate;
            this.SapiManager.VoiceVolume = _speechVolume;

            SelectVoice();
        }

        private void SelectVoice()
        {
            if (_voices.Count > 0)
            {
                if (rdPersonName.Checked == true)
                {
                    this.SapiManager.SelectVoice(cmbPersons.Text);
                }

                if (rdSelectGender.Checked == true)
                {
                    VoiceGender gender = VoiceGender.NotSet;

                    if (cmbGender.Text.Equals(VoiceGender.Female.ToString()))
                    {
                        gender = VoiceGender.Female;
                    }
                    else if (cmbGender.Text.Equals(VoiceGender.Male.ToString()))
                    {
                        gender = VoiceGender.Male;
                    }
                    else if (cmbGender.Text.Equals(VoiceGender.Neutral.ToString()))
                    {
                        gender = VoiceGender.Neutral;
                    }
                    else if (cmbGender.Text.Equals(VoiceGender.NotSet.ToString()))
                    {
                        gender = VoiceGender.NotSet;
                    }

                    VoiceAge age = VoiceAge.NotSet;
                    if (cmbAge.Text.Equals(VoiceAge.Adult.ToString()))
                    {
                        age = VoiceAge.Adult;
                    }
                    else if (cmbAge.Text.Equals(VoiceAge.Child.ToString()))
                    {
                        age = VoiceAge.Child;
                    }
                    else if (cmbAge.Text.Equals(VoiceAge.NotSet.ToString()))
                    {
                        age = VoiceAge.NotSet;
                    }
                    else if (cmbAge.Text.Equals(VoiceAge.Senior.ToString()))
                    {
                        age = VoiceAge.Senior;
                    }
                    else if (cmbAge.Text.Equals(VoiceAge.Teen.ToString()))
                    {
                        age = VoiceAge.Teen;
                    }
                    this.SapiManager.SelectVoice(gender, age);
                }
            }
        }

        private bool CheckIfAlreadyExists(ComboBox.ObjectCollection objectCollection, string str)
        {
            foreach (Object obj in objectCollection)
            {
                if (obj.ToString() == str)
                {
                    return true;
                }
            }
            return false;
        }

        private void PopulateProperties()
        {
            this.trackBarRate.Value = this._speechRate = this.SapiManager.VoiceRate;
            this.trackBarVolume.Value = this._speechVolume = this.SapiManager.VoiceVolume;

            VoiceInfo voice = SapiManager.CurrentVoice;

            if (!string.IsNullOrEmpty(voice.Name))
            {
                rdPersonName.Checked = true;
                cmbPersons.SelectedItem = voice.Name;
            }
            else
            {
                rdSelectGender.Checked = true;
                cmbGender.SelectedItem = voice.Gender.ToString();
                cmbAge.SelectedItem = voice.Age.ToString();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            OnCanceled(new EventArgs());
        }

        private void OnCanceled(EventArgs e)
        {
            if (SettingsCanceled != null)
                SettingsCanceled(this, e);
        }

        private void OnApplied(EventArgs e)
        {
            if (SettingsApplied != null)
                SettingsApplied(this, e);
        }

        #endregion Private
        
        #endregion Methods       
    }
}